module IDU(
    input clk,
    input [31:0] inst,
    input wire rst,
    input wire [4:0] rf_waddr,
    input wire [31:0]rf_wdata,
    input wire rf_we,
    input wire[31:0] pc_current,
    input wire ID_block,
    input wire IF_ready,
    //id级转发控�?
    input wire[1:0]src1_op,
    input wire[1:0]src2_op,
    //特权转发控制
    input wire[1:0]csr_op,
    //转发源输�?
    input wire[31:0]dest_value_from_ID_EX,
    input wire[31:0]dest_value_from_EX_MEM,
    input wire[31:0]dest_value_from_MEM_WB,
    input wire[31:0]csr_value_from_ID_EX,
    input wire[31:0]csr_value_from_EX_MEM,

    output wire need_ID_forward1,
    output wire need_ID_forward2,
    output wire[31:0]br_target,
    output wire br_taken,
    output wire is_write_reg,
    output wire is_read_mem,
    output wire is_write_mem,
    output wire res_from_mem,
    output wire [3:0] mem_op,
    output wire [18:0] alu_op,
    output wire[31:0] rf_rdata1,
    output wire[31:0] rf_rdata2,
    output wire [4:0] rf_raddr1,
    output wire [4:0] rf_raddr2,
    output wire [4:0] dest,
    output wire [31:0] imm,
    output wire src2_is_imm,
    output wire src1_is_pc,
    output wire [31:0]pc,

    ///exc
    input wire        exc_in,
    input wire [31:0] exc_pc,
    input wire [ 6:0] exc_entry,
    input wire [31:0] badv,
    input wire [13:0] csr_rf_waddr,
    input wire [31:0] csr_rf_wdata,
    input wire        csr_rf_we,

    output wire       is_write_csr,
    output wire[13:0] csr_dest,
    output wire[13:0] csr_rdest,
    output wire[31:0] csr_wdata,
    output wire[31:0] csr_rdata,
    output wire       res_from_csr,

    output wire       exc,
    output wire[5:0]  ecode,
    output wire       esubcode,
    output wire       exc_oc
);
wire        dst_is_r1;
wire        src_reg_is_rd;
wire is_imm_4;
wire [31:0] br_offs;
wire [31:0] jirl_offs;

//对inst的拆�?,寄存器号,立即�?
wire [ 5:0] op_31_26;
wire [ 3:0] op_25_22;
wire [ 1:0] op_21_20;
wire [ 4:0] op_19_15;
wire [ 4:0] rd;
wire [ 4:0] rj;
wire [ 4:0] rk;
wire [11:0] i12;
wire [19:0] i20;
wire [15:0] i16;
wire [25:0] i26;
wire [63:0] op_31_26_d;
wire [15:0] op_25_22_d;
wire [ 3:0] op_21_20_d;
wire [31:0] op_19_15_d;
assign op_31_26  = inst[31:26];
assign op_25_22  = inst[25:22];
assign op_21_20  = inst[21:20];
assign op_19_15  = inst[19:15];
assign rd   = inst[ 4: 0];
assign rj   = inst[ 9: 5];
assign rk   = inst[14:10];
assign i12  = inst[21:10];
assign i20  = inst[24: 5];
assign i16  = inst[25:10];
assign i26  = {inst[ 9: 0], inst[25:10]};
decoder_6_64 u_dec0(.in(op_31_26 ), .out(op_31_26_d ));
decoder_4_16 u_dec1(.in(op_25_22 ), .out(op_25_22_d ));
decoder_2_4  u_dec2(.in(op_21_20 ), .out(op_21_20_d ));
decoder_5_32 u_dec3(.in(op_19_15 ), .out(op_19_15_d ));

wire[31:0] rj_value;
wire[31:0] rkd_value;
//指令信号
//整数指令
wire        inst_add_w;
wire        inst_sub_w;
wire        inst_addi_w;
wire        inst_lu12i_w;
wire        inst_slt;
wire        inst_sltu;
wire        inst_slti;
wire        inst_sltui;
wire        inst_pcaddu12i;
wire        inst_and;
wire        inst_or;
wire        inst_nor;
wire        inst_xor;
wire        inst_andi;
wire        inst_ori;
wire        inst_xori;
wire        inst_nop;
wire        inst_mul_w;
wire        inst_mulh_w;
wire        inst_mulh_wu;
wire        inst_div_w;
wire        inst_mod_w;
wire        inst_div_wu;
wire        inst_mod_wu;
wire        inst_sll_w;
wire        inst_srl_w;
wire        inst_sra_w;
wire        inst_slli_w;
wire        inst_srli_w;
wire        inst_srai_w;
wire        inst_beq;
wire        inst_bne;
wire        inst_blt;
wire        inst_bge;
wire        inst_bltu;
wire        inst_bgeu;
wire        inst_b;
wire        inst_bl;
wire        inst_jirl;
wire        inst_ld_b;
wire        inst_ld_h;
wire        inst_ld_w;
wire        inst_ld_bu;
wire        inst_ld_hu;
wire        inst_st_b;
wire        inst_st_h;
wire        inst_st_w;
assign inst_add_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00];
assign inst_sub_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02];
assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha];
assign inst_lu12i_w= op_31_26_d[6'h05] & ~inst[25];
assign inst_slt    = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04];
assign inst_sltu   = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05];
assign inst_slti   = op_31_26_d[6'h00] & op_25_22_d[4'h8];
assign inst_sltui  = op_31_26_d[6'h00] & op_25_22_d[4'h9];
assign inst_pcaddu12i = op_31_26_d[6'h07] & ~inst[25];
assign inst_and    = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09];
assign inst_or     = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a];
assign inst_nor    = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08];
assign inst_xor    = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b];
assign inst_andi   = op_31_26_d[6'h00] & op_25_22_d[4'b1101];
assign inst_ori    = op_31_26_d[6'h00] & op_25_22_d[4'b1110];
assign inst_xori   = op_31_26_d[6'h00] & op_25_22_d[4'b1111];
assign inst_nop    = op_31_26_d[6'h00] & op_25_22_d[4'b1101] & inst[21:0]==22'b0;
assign inst_mul_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b11000];
assign inst_mulh_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b11001];
assign inst_mulh_wu= op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b11010];
assign inst_div_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'b00000];
assign inst_mod_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'b00001];
assign inst_div_wu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'b00010];
assign inst_mod_wu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'b00011];
assign inst_sll_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b01110];
assign inst_srl_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b01111];
assign inst_sra_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'b10000];
assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01];
assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09];
assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11];
assign inst_beq    = op_31_26_d[6'h16];
assign inst_bne    = op_31_26_d[6'h17];
assign inst_blt    = op_31_26_d[6'h18];
assign inst_bge    = op_31_26_d[6'h19];
assign inst_bltu   = op_31_26_d[6'h1A];
assign inst_bgeu   = op_31_26_d[6'h1B];
assign inst_b      = op_31_26_d[6'h14];
assign inst_bl     = op_31_26_d[6'h15];
assign inst_jirl   = op_31_26_d[6'h13];
assign inst_ld_b   = op_31_26_d[6'h0A] & op_25_22_d[4'h0];
assign inst_ld_h   = op_31_26_d[6'h0A] & op_25_22_d[4'h1];
assign inst_ld_w   = op_31_26_d[6'h0a] & op_25_22_d[4'h2];
assign inst_ld_bu  = op_31_26_d[6'h0A] & op_25_22_d[4'h8];
assign inst_ld_hu  = op_31_26_d[6'h0A] & op_25_22_d[4'h9];
assign inst_st_b   = op_31_26_d[6'h0A] & op_25_22_d[4'h4];
assign inst_st_h   = op_31_26_d[6'h0A] & op_25_22_d[4'h5];
assign inst_st_w   = op_31_26_d[6'h0a] & op_25_22_d[4'h6];
//counter
wire inst_rdcntvl_w;
wire inst_rdcntvh_w;
wire inst_rdcntid;
//exc
wire inst_syscall;
wire inst_break;
wire exc_sys;
wire exc_brk;
wire exc_ertn;
wire exc_ine;
wire [14:0]exc_sbcode;
wire [12:0]int;
wire ie;

//特权指令
wire inst_csrrd;
wire inst_csrwr;
wire inst_csrxchg;
wire inst_ertn;
wire inst_zero;

reg [31:0]  exc_addr;
reg         exc_int;
reg [31:0]  csr_rnum1_exc_r;
reg [31:0]  csr_rnum2_exc_r;
reg [31:0]  csr_rnum1_ertn_r;
reg [31:0]  csr_rnum2_ertn_r;
reg [13:0]  csr_wnum_exc_r;
reg [13:0]  csr_wnum_ertn_r;
reg [31:0]  csr_wdata_exc_r;
reg [31:0]  csr_wdata_ertn_r;
reg         csr_we_exc_h = 0;
reg         csr_we_ertn_h = 0;

wire[13:0]  csr_rnum_w;
wire[13:0]  csr_rnum1_w;
wire[13:0]  csr_rnum2_w;
wire[13:0]  csr_wnum_w;
wire[31:0]  csr_wdata_w;
wire[31:0]  csr_rdata_w;
wire[31:0]  csr_rdata1_w;
wire[31:0]  csr_rdata2_w;
wire[31:0]  csr_xdata_w;
wire        csr_we_w;
wire        csr_we_h_w;
wire        csr_busy;

reg         exc_taken = 0;
reg         ertn_taken= 0; 
reg         csr_busy_exc = 0;
reg         csr_busy_ertn= 0;
reg [3:0]   ertn_count= 4'b0000;
reg [3:0]   exc_count = 4'b0000;
reg         reset_exc = 0;
reg         reset_ertn = 0;
reg[31:0]   exc_pc_catch;
reg[ 6:0]   exc_entry_catch;
reg[31:0]   badv_catch;

reg[31:0]   CRMD_exc;
reg[31:0]   PRMD_exc;
reg[31:0]   CRMD_ertn;
reg[31:0]   PRMD_ertn;

reg[31:0] ertn_addr;


assign inst_csrrd  = op_31_26_d[6'h01] & inst[25:24] == 2'b00 & inst[9:5] == 5'b00000;
assign inst_csrwr  = op_31_26_d[6'h01] & inst[25:24] == 2'b00 & inst[9:5] == 5'b00001;
assign inst_csrxchg= op_31_26_d[6'h01] & inst[25:24] == 2'b00 & inst[9:5] != 5'b00000 & inst[9:5] != 5'b00001;
assign inst_ertn   = inst == 32'b00000110010010000011100000000000;
assign inst_syscall= op_31_26_d[0] & op_25_22_d[0] & op_21_20_d[2'b10] & op_19_15_d[5'h16];
assign inst_break  = op_31_26_d[0] & op_25_22_d[0] & op_21_20_d[2'b10] & op_19_15_d[5'h14];
assign inst_zero   = inst == 0;

assign exc_sys = inst_syscall;
assign exc_brk = inst_break;
assign exc_ertn= inst_ertn;
assign exc_ine = ~( inst_add_w|
                    inst_sub_w|
                    inst_addi_w|
                    inst_lu12i_w|
                    inst_slt|
                    inst_sltu|
                    inst_slti|
                    inst_sltui|
                    inst_pcaddu12i|
                    inst_and|
                    inst_or|
                    inst_nor|
                    inst_xor|
                    inst_andi|
                    inst_ori|
                    inst_xori|
                    inst_nop|
                    inst_mul_w|
                    inst_mulh_w|
                    inst_mulh_wu|
                    inst_div_w|
                    inst_mod_w|
                    inst_div_wu|
                    inst_mod_wu|
                    inst_sll_w|
                    inst_srl_w|
                    inst_sra_w|
                    inst_slli_w|
                    inst_srli_w|
                    inst_srai_w|
                    inst_beq|
                    inst_bne|
                    inst_blt|
                    inst_bge|
                    inst_bltu|
                    inst_bgeu|
                    inst_b|
                    inst_bl|
                    inst_jirl|
                    inst_ld_b|
                    inst_ld_h|
                    inst_ld_w|
                    inst_ld_bu|
                    inst_ld_hu|
                    inst_st_b|
                    inst_st_h|
                    inst_st_w|
                    inst_syscall|
                    inst_break|
                    inst_csrrd|
                    inst_csrwr|
                    inst_csrxchg|
                    inst_ertn|
                    inst_rdcntid|
                    inst_rdcntvh_w|
                    inst_rdcntvl_w
                );
                    
always@(posedge clk)begin
    if(IF_ready && (int != 0 && ie)) exc_int <= 1;
    else exc_int <= 0;
end

assign exc     = (~ID_block) && (exc_sys || exc_brk || exc_ine || exc_int || exc_ertn);
assign ecode   = exc_sys ? 6'h0b :
                 exc_brk ? 6'h0c :
                 exc_ine ? 6'h0d : 
                 exc_ertn? 6'h0a : 0;
assign esubcode= 0;
assign exc_sbcode = inst[14:0];
assign exc_oc = reset_ertn | reset_exc;
assign csr_busy = csr_busy_ertn | csr_busy_exc;

//例外处理
always@(posedge clk)begin
    if(exc_in && reset_exc == 0 && exc_entry != 7'h0a) begin
        exc_count = 4'b0111;
        reset_exc = 1;
        exc_entry_catch <= exc_entry;
        exc_pc_catch <= exc_pc;
        badv_catch <= badv;
    end
    case(exc_count)
        4'b0111:begin
            //读CRMD、PRMD
            csr_busy_exc <= 1;
            csr_rnum1_exc_r <= 14'h0000;
            csr_rnum2_exc_r <= 14'h0001;
            exc_count <= 4'b0110;
        end
        4'b0110:begin
            //写PRMD
            CRMD_exc <= csr_rdata1_w;
            PRMD_exc <= csr_rdata2_w;
            csr_wnum_exc_r <= 14'h0001;
            csr_wdata_exc_r <= {csr_rdata2_w[31:3],csr_rdata1_w[2:0]};
            csr_we_exc_h <= 1;
            exc_count <= 4'b0101;
        end
        4'b0101:begin
            //写CRMD
            csr_wnum_exc_r <= 14'h0000;
            csr_wdata_exc_r <= {CRMD_exc[31:3],3'b0};
            csr_we_exc_h <= 1;
            exc_count <= 4'b0100;
        end
        4'b0100:begin
            //写出错虚地址
            csr_wnum_exc_r <= 14'h0007;
            csr_wdata_exc_r <= badv_catch;
            csr_we_exc_h <= exc_entry_catch[5:0] == 6'h08 ||
                            exc_entry_catch == 6'h09;
            //读跳转地址
            csr_rnum1_exc_r <= 14'h000c;
            exc_count <= 4'b0011;
        end
        4'b0011:begin
            //写入pc
            csr_wnum_exc_r <= 14'h0006;
            csr_wdata_exc_r <= exc_pc_catch;
            csr_we_exc_h <= 1;
            //写跳转地址
            exc_addr <= csr_rdata1_w;
            exc_count <= 4'b0010;
        end
        4'b0010:begin
            //写入例外号
            csr_wnum_exc_r <= 14'h0005;
            csr_wdata_exc_r <= {9'b0,exc_entry_catch,3'b0,int};
            csr_we_exc_h <= 1;
            exc_count <= 4'b0001;
        end 
        4'b0001:begin
            reset_exc <= 0;
            exc_taken <= 1;
            csr_we_exc_h <= 0;
            csr_busy_exc <= 0;
            exc_count <= 4'b0000;
        end
        4'b0000:begin
            if(ID_block == 0)exc_taken <= 0;
            exc_count <= 4'b0000;
        end
    endcase
end

//例外返回
always@(posedge clk)begin
    if(exc_in && reset_ertn == 0 && exc_entry == 7'h0a) begin
        ertn_count = 4'b0100;
        reset_ertn = 1;
    end
    case(ertn_count)
        4'b0100:begin
            csr_busy_ertn <= 1;
            csr_rnum1_ertn_r <= 14'h0000;
            csr_rnum2_ertn_r <= 14'h0001;
            ertn_count <= 4'b0011; 
        end
        4'b0011:begin
            CRMD_ertn <= csr_rdata1_w;
            PRMD_ertn <= csr_rdata2_w;
            ertn_count <= 4'b0010;
        end
        4'b0010:begin
            csr_wnum_ertn_r <= 14'h0000;
            csr_wdata_ertn_r <= {CRMD_ertn[31:3],PRMD_ertn[2:0]};
            csr_we_ertn_h <= 1;
            //读出era
            csr_rnum1_ertn_r <= 14'h0006;
            ertn_count <= 4'b0001;
        end
        4'b0001:begin
            ertn_addr <= csr_rdata1_w;
            reset_ertn <= 0;
            ertn_taken <= 1;
            csr_we_ertn_h <= 0;
            csr_busy_ertn <= 0;
            ertn_count <= 4'b0000;
        end
        4'b0000:begin
            if(ID_block == 0)ertn_taken <= 0;
            ertn_count <= 4'b0000;
        end
    endcase
end

assign csr_rdest  = csr_rnum_w;
assign csr_rnum_w = inst_rdcntid ? 14'h0040 : inst[23:10];
assign csr_rnum1_w= csr_busy_exc ? csr_rnum1_exc_r : csr_rnum1_ertn_r;
assign csr_rnum2_w= csr_busy_exc ? csr_rnum2_exc_r : csr_rnum2_ertn_r;
assign csr_wnum_w = ~csr_busy ? csr_rf_waddr : 
                    csr_busy_exc ? csr_wnum_exc_r : csr_wnum_ertn_r;
assign csr_wdata_w= ~csr_busy ? csr_rf_wdata : 
                    csr_busy_exc ? csr_wdata_exc_r: csr_wdata_ertn_r;
assign csr_we_w   = csr_rf_we;
assign csr_we_h_w = csr_we_exc_h | csr_we_ertn_h;

wire [31:0] tid;
CSR csr1 (
    .clk        (clk                      ),
    .csr_rnum   (csr_rnum_w               ),
    .csr_rnum1  (csr_rnum1_w              ),
    .csr_rnum2  (csr_rnum2_w              ),
    .csr_wnum   (csr_wnum_w               ),
    .rdata      (csr_rdata_w              ),
    .rdata1     (csr_rdata1_w             ),
    .rdata2     (csr_rdata2_w             ),
    .int        (int                      ),
    .wdata      (csr_wdata_w              ),
    .we         (csr_we_w                 ),
    .we_h       (csr_we_h_w               ),
    .reset      (rst                      ),
    .ie         (ie                       )
);

wire[31:0]csr_rdata1_w_after_FORWARD;
assign csr_rdata1_w_after_FORWARD = csr_op[1:0]==2'b10 ? csr_value_from_ID_EX:
                                    csr_op[1:0]==2'b11 ? csr_value_from_EX_MEM : csr_rdata_w;

wire [31:0]timeval;
wire timeinst;
assign timeinst = inst_rdcntvh_w | inst_rdcntvl_w;


assign is_write_csr= inst_csrwr | inst_csrxchg;
assign csr_dest    = inst[23:10];
assign csr_wdata   = inst_csrxchg ? csr_xdata_w : rf_rdata2;
assign csr_rdata   = timeinst ? timeval : csr_rdata1_w_after_FORWARD;
assign res_from_csr= inst_csrrd | inst_csrwr | inst_csrxchg | 
                     inst_rdcntvh_w | inst_rdcntvl_w | inst_rdcntid;

assign csr_xdata_w[31] = rf_rdata1[31] == 1 ? rf_rdata2[31] : csr_rdata_w[31];
assign csr_xdata_w[30] = rf_rdata1[30] == 1 ? rf_rdata2[30] : csr_rdata_w[30]; 
assign csr_xdata_w[29] = rf_rdata1[29] == 1 ? rf_rdata2[29] : csr_rdata_w[29]; 
assign csr_xdata_w[28] = rf_rdata1[28] == 1 ? rf_rdata2[28] : csr_rdata_w[28]; 
assign csr_xdata_w[27] = rf_rdata1[27] == 1 ? rf_rdata2[27] : csr_rdata_w[27]; 
assign csr_xdata_w[26] = rf_rdata1[26] == 1 ? rf_rdata2[26] : csr_rdata_w[26]; 
assign csr_xdata_w[25] = rf_rdata1[25] == 1 ? rf_rdata2[25] : csr_rdata_w[25]; 
assign csr_xdata_w[24] = rf_rdata1[24] == 1 ? rf_rdata2[24] : csr_rdata_w[24]; 
assign csr_xdata_w[23] = rf_rdata1[23] == 1 ? rf_rdata2[23] : csr_rdata_w[23]; 
assign csr_xdata_w[22] = rf_rdata1[22] == 1 ? rf_rdata2[22] : csr_rdata_w[22]; 
assign csr_xdata_w[21] = rf_rdata1[21] == 1 ? rf_rdata2[21] : csr_rdata_w[21]; 
assign csr_xdata_w[20] = rf_rdata1[20] == 1 ? rf_rdata2[20] : csr_rdata_w[20]; 
assign csr_xdata_w[19] = rf_rdata1[19] == 1 ? rf_rdata2[19] : csr_rdata_w[19]; 
assign csr_xdata_w[18] = rf_rdata1[18] == 1 ? rf_rdata2[18] : csr_rdata_w[18]; 
assign csr_xdata_w[17] = rf_rdata1[17] == 1 ? rf_rdata2[17] : csr_rdata_w[17]; 
assign csr_xdata_w[16] = rf_rdata1[16] == 1 ? rf_rdata2[16] : csr_rdata_w[16]; 
assign csr_xdata_w[15] = rf_rdata1[15] == 1 ? rf_rdata2[15] : csr_rdata_w[15]; 
assign csr_xdata_w[14] = rf_rdata1[14] == 1 ? rf_rdata2[14] : csr_rdata_w[14]; 
assign csr_xdata_w[13] = rf_rdata1[13] == 1 ? rf_rdata2[13] : csr_rdata_w[13]; 
assign csr_xdata_w[12] = rf_rdata1[12] == 1 ? rf_rdata2[12] : csr_rdata_w[12]; 
assign csr_xdata_w[11] = rf_rdata1[11] == 1 ? rf_rdata2[11] : csr_rdata_w[11]; 
assign csr_xdata_w[10] = rf_rdata1[10] == 1 ? rf_rdata2[10] : csr_rdata_w[10]; 
assign csr_xdata_w[ 9] = rf_rdata1[ 9] == 1 ? rf_rdata2[ 9] : csr_rdata_w[ 9]; 
assign csr_xdata_w[ 8] = rf_rdata1[ 8] == 1 ? rf_rdata2[ 8] : csr_rdata_w[ 8]; 
assign csr_xdata_w[ 7] = rf_rdata1[ 7] == 1 ? rf_rdata2[ 7] : csr_rdata_w[ 7]; 
assign csr_xdata_w[ 6] = rf_rdata1[ 6] == 1 ? rf_rdata2[ 6] : csr_rdata_w[ 6]; 
assign csr_xdata_w[ 5] = rf_rdata1[ 5] == 1 ? rf_rdata2[ 5] : csr_rdata_w[ 5]; 
assign csr_xdata_w[ 4] = rf_rdata1[ 4] == 1 ? rf_rdata2[ 4] : csr_rdata_w[ 4]; 
assign csr_xdata_w[ 3] = rf_rdata1[ 3] == 1 ? rf_rdata2[ 3] : csr_rdata_w[ 3]; 
assign csr_xdata_w[ 2] = rf_rdata1[ 2] == 1 ? rf_rdata2[ 2] : csr_rdata_w[ 2]; 
assign csr_xdata_w[ 1] = rf_rdata1[ 1] == 1 ? rf_rdata2[ 1] : csr_rdata_w[ 1]; 
assign csr_xdata_w[ 0] = rf_rdata1[ 0] == 1 ? rf_rdata2[ 0] : csr_rdata_w[ 0]; 

//计数�?
assign inst_rdcntid   = inst[31:10] == 22'h00018 & rd == 0;
assign inst_rdcntvl_w = inst[31:10] == 22'h00018 & rj == 0;
assign inst_rdcntvh_w = inst[31:10] == 22'h00019 & rj == 0;
wire hl;
assign hl = inst_rdcntvh_w ? 1 : 0;

counter counter1(
    .clk(clk),
    .reset(rst),
    .horl(hl),
    .time1(timeval)    
);
//加法
assign alu_op[ 0] = inst_add_w |
                    inst_addi_w | inst_pcaddu12i|
                    inst_ld_w | inst_st_w | 
                    inst_jirl | inst_bl|
                    inst_ld_b |inst_ld_h|
                    inst_ld_bu |inst_ld_hu|
                    inst_st_b |inst_st_h;
//减法
assign alu_op[ 1] = inst_sub_w;
//有符号小于则置位
assign alu_op[ 2] = inst_slt | inst_slti;
//无符�?
assign alu_op[ 3] = inst_sltu |inst_sltui;
//�?
assign alu_op[ 4] = inst_and | inst_andi;
//�?
assign alu_op[ 5] = inst_nor;
//�?
assign alu_op[ 6] = inst_or | inst_ori;
//异或
assign alu_op[ 7] = inst_xor | inst_xori;
//逻辑左移
assign alu_op[ 8] = inst_slli_w|inst_sll_w;
//逻辑左移
assign alu_op[ 9] = inst_srli_w|inst_srl_w;
//算术右移
assign alu_op[10] = inst_srai_w|inst_sra_w;
//
assign alu_op[11] = inst_lu12i_w;
//乘法有符�?
assign alu_op[12] = inst_mul_w;
//取高�?
assign alu_op[13] = inst_mulh_w;
//无符号乘,取高�?
assign alu_op[14] = inst_mulh_wu;
//有符�?
assign alu_op[15] = inst_div_w;
//无符�?
assign alu_op[16] = inst_div_wu;
//有符�?
assign alu_op[17] = inst_mod_w;
//无符�?
assign alu_op[18] = inst_mod_wu;

//mem_op不全
assign mem_op[0] = inst_st_w | inst_ld_w ;
assign mem_op[1] = inst_st_h | inst_ld_h | inst_ld_hu;
assign mem_op[2] = inst_st_b | inst_ld_b | inst_ld_bu;
assign mem_op[3] = inst_ld_bu| inst_ld_hu;
//立即数处�?
wire need_ui5;
wire need_si12;
wire need_ui12;
wire need_si16;
wire need_si20;
wire need_si26;

assign need_ui5   =  inst_slli_w | inst_srli_w | inst_srai_w ;
assign need_si12  =  inst_addi_w | inst_ld_w | inst_st_w |
                     inst_ld_b   | inst_st_b |inst_ld_bu |inst_ld_h|inst_ld_hu|inst_st_h| inst_slti |inst_sltui;
assign need_ui12 =   inst_andi   | inst_ori  |inst_nop   |inst_xori;
assign need_si16  =  inst_jirl   | inst_beq  | inst_bne  | inst_blt | inst_bge | inst_bltu | inst_bgeu;
assign need_si20  =  inst_lu12i_w| inst_pcaddu12i;
assign need_si26  =  inst_b | inst_bl;

assign is_imm_4  =  inst_jirl | inst_bl;

assign imm = is_imm_4 ? 32'h4                       :
             need_si20 ? {i20[19:0], 12'b0}         :
             need_ui12 ? {12'b0,i12[11:0]}          :
             need_ui5  ? rk                         :
             need_si12 ? {{20{i12[11]}}, i12[11:0]}:0 ;

assign br_offs = need_si26 ? {{ 4{i26[25]}}, i26[25:0], 2'b0} :
                 need_si16 ? {{14{i16[15]}}, i16[15:0], 2'b0} : 0 ;
assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0};

assign src_reg_is_rd =  inst_st_w | 
                        inst_st_b | 
                        inst_st_h |
                        inst_beq  | 
                        inst_bne  | 
                        inst_blt  | 
                        inst_bge  | 
                        inst_bltu |
                        inst_bgeu |
                        inst_csrwr|
                        inst_csrxchg;

//alu操作数�?�择控制
assign src1_is_pc    = inst_jirl | inst_bl|inst_pcaddu12i;
assign src2_is_imm   = inst_slti   |
                       inst_sltui  |
                       inst_slli_w |
                       inst_srli_w |
                       inst_srai_w |
                       inst_addi_w |
                       inst_ld_w   | inst_ld_b | inst_ld_bu | inst_ld_h | inst_ld_hu |
                       inst_st_w   | inst_st_b | inst_st_h  |
                       inst_lu12i_w|
                       inst_jirl   |
                       inst_bl     |
                       inst_andi   |
                       inst_ori    |
                       inst_xori   |
                       inst_pcaddu12i;
//访存控制
assign is_read_mem   = inst_ld_w | inst_ld_b|inst_ld_h|inst_ld_bu|inst_ld_hu ;
assign res_from_mem  = inst_ld_w | inst_ld_b|inst_ld_h|inst_ld_bu|inst_ld_hu ;
assign is_write_mem  = inst_st_w | inst_st_b|inst_st_h;

//写寄存器控制
assign dst_is_r1     = inst_bl;
assign dest          = dst_is_r1 ? 5'd1 : inst_rdcntid ? rj : rd;
assign is_write_reg  = ~exc_ine & dest!=5'b0 & ~inst_st_w & ~inst_st_b & ~inst_st_h & ~inst_beq & ~inst_bne & ~inst_blt & ~inst_bge & ~inst_bltu & ~inst_bgeu & ~inst_b;//不全

//访问寄存�?
assign rf_raddr1 = rj;
assign rf_raddr2 = src_reg_is_rd ? rd :rk;

regfile u_regfile(
    .clk    (clk      ),
    .raddr1 (rf_raddr1),
    .rdata1 (rj_value),
    .raddr2 (rf_raddr2),
    .rdata2 (rkd_value),
    .we     (rf_we    ),
    .waddr  (rf_waddr ),
    .wdata  (rf_wdata )
    );
assign need_ID_forward1=0;//
assign need_ID_forward2=0;//
assign rf_rdata1=(src1_op==2'b01)?dest_value_from_ID_EX:
                 (src1_op==2'b10)?dest_value_from_EX_MEM:
                 (src1_op==2'b11)?dest_value_from_MEM_WB:
                 rj_value;

assign rf_rdata2=(src2_op==2'b01)?dest_value_from_ID_EX:
                 (src2_op==2'b10)?dest_value_from_EX_MEM:
                 (src2_op==2'b11)?dest_value_from_MEM_WB:
                 rkd_value;

//跳转条件及跳转信�?
assign rj_eq_rd = (rf_rdata1 == rf_rdata2);
assign rj_big_rd = ($signed(rf_rdata1) < $signed(rf_rdata2));
assign rj_bigu_rd = (rf_rdata1 < rf_rdata2); 
assign br_taken = (   inst_beq  &&  rj_eq_rd
                   || inst_bne  && (!rj_eq_rd)
                   || inst_blt  &&  rj_big_rd
                   || inst_bge  && (!rj_big_rd)
                   || inst_bltu &&  rj_bigu_rd
                   || inst_bgeu && (!rj_bigu_rd)
                   || inst_jirl
                   || inst_bl
                   || inst_b
                   || exc_taken
                   || ertn_taken
                  );
assign br_target =     exc_taken ? exc_addr:
                       ertn_taken ? ertn_addr:
                       (inst_beq 
                    || inst_bne 
                    || inst_blt
                    || inst_bltu
                    || inst_bge
                    || inst_bgeu
                    || inst_bl 
                    || inst_b ) ? (pc_current + br_offs):
                    (rj_value + jirl_offs);

endmodule